package com.wf.protobuf;

import com.wf.protobuf.builder.ProtobufMsgBuilder;
import com.wf.protobuf.domain.ProtoMsg;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * Protobuf消息测试
 *
 * @author wf
 * @since 2022/5/28
 */
@Slf4j
public class ProtobufDemo {
    @Test
    public void testProtoMsg1() throws IOException {
        ProtoMsg protoMsg = ProtobufMsgBuilder.buildMsg(1000, "testHelloWorld");

        // 转为字节数组
        byte[] data = protoMsg.toByteArray();
        // 可以用于网络传输，保存到内存或外存中
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        outputStream.write(data);
        data = outputStream.toByteArray();

        // 二进制字节数组反序列化为Protobuf对象
        ProtoMsg inMsg = ProtoMsg.parseFrom(data);
        log.info("inMsg id is: {}", inMsg.getId());
        log.info("inMsgContent is: {}", inMsg.getContent());
    }

    @Test
    public void testProtoMsg2() throws IOException {
        ProtoMsg protoMsg = ProtobufMsgBuilder.buildMsg(1000, "testHelloWorld");
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        // 将二进制字节写入到输出流
        protoMsg.writeTo(outputStream);
        ByteArrayInputStream in = new ByteArrayInputStream(outputStream.toByteArray());
        // 将二进制流反序列化为对象
        ProtoMsg inMsg = ProtoMsg.parseFrom(in);
        log.info("inMsg id is: {}", inMsg.getId());
        log.info("inMsgContent is: {}", inMsg.getContent());
    }

    @Test
    public void testProtoMsg3() throws IOException {
        ProtoMsg protoMsg = ProtobufMsgBuilder.buildMsg(1000, "testHelloWorld");
        // 序列化到二进制码流
        ByteArrayOutputStream outputStream =
                new ByteArrayOutputStream();
        protoMsg.writeDelimitedTo(outputStream);
        ByteArrayInputStream inputStream =
                new ByteArrayInputStream(outputStream.toByteArray());
        // 从二进制码字节流反序列化成Protobuf对象,
        // 从输入流中先读取varint32类型的长度值，然后根据长度值读取此消息的二进制字节，再反序列化得到POJO新的实例，解决了粘包/半包的问题
        ProtoMsg inMsg = ProtoMsg.parseDelimitedFrom(inputStream);
        log.info("id:=" + inMsg.getId());
        log.info("content:=" + inMsg.getContent());
    }
}
